// (C) Copyright 2009, 2010 Communications Programming, Inc.
/***************************************************************************************************************
*  Name: flash.c
*
*	Description:	This module contains the code modules for the 
*					PIC32 flash memory read/write routines to allow a portion
*					of dynamically written memory to survive power off/on.
*
*					FlashRead obtains saved data from the flash mem area
*					FlashWrite obtains saved data from the flash mem area
*
*  Calling Parameters:
*  
*	INT16 FlashRead( UINT16	flashMemOffset,	// offset into flash mem area
*					 UINT16	len,			// byte length to read
*					 UINT8	*outBuf );		// out buffer to recv data read
*
*	INT16 FlashWrite( UINT16	flashMemOffset,	// offset into flash mem area
*					  UINT16	len,			// byte length to write
*					  UINT8		*inBuf );		// in buffer to write
*
*	The sum of the offset and len parameters should not exceed FLASH_SIZE
*	Returns 0 for success, or non-0 error codes in flash.h if failed
*
*  Revision History:
*  Date    Who  Comments
*  ------  ---  -----------------------------------------------------------------------------------------
*  101128  RLP	Created.
*
***************************************************************************************************************/

#include <stdlib.h>
#include <userLib.h>
#include <cmn\flash.h>

// allocate FLASH_SIZE bytes of storage for the flash memory area

#if (__C32_VERSION__ < 200)

#define NVM_ALLOCATE(name, bytes) volatile UINT8 name[(bytes)] \
     __attribute__ ((aligned(BYTE_PAGE_SIZE),section(".text,\"ax\",@progbits #"))) = \
     { [0 ...(bytes)-1] = 0xFF } 
     
#else

#define NVM_ALLOCATE(name,bytes) volatile unsigned char name[(bytes)] \
   __attribute__((aligned(BYTE_PAGE_SIZE),space(prog),section(".nvm"))) = \
   { [0 ... (bytes)-1] = 0xFF }
     
#endif
     
NVM_ALLOCATE(flashMem, FLASH_SIZE);
     

// Reads flash memory 

INT16 FlashRead( UINT16	flashMemOffset,	// offset into flash mem area
				 UINT16	len,			// byte length to read
				 UINT8	*outBuf )		// out buffer to recv data read
{
	if( flashMemOffset + len > FLASH_SIZE )
		return( FLASH_BAD_LEN );
	memcpy( outBuf, (void *)&flashMem[flashMemOffset], len );
	return(FLASH_SUCCESS);
}

// Writes flash memory

INT16 FlashWrite( UINT16	flashMemOffset,	// offset into flash mem area
				  UINT16	len,			// byte length to write
				  UINT8		*inBuf )		// in buffer to write
{
	UINT32	rc;						// retn code
	UINT8	copyBuf[FLASH_SIZE];	// copy of flashMem
	UINT8	pageBuf[FLASH_SIZE];	// page buffer for NVMProgram

	if( flashMemOffset + len > FLASH_SIZE )
		return( FLASH_BAD_LEN );

	// get working copy of flash mem

	memcpy( copyBuf, (void *)flashMem, FLASH_SIZE );
	
	// make desired write to specific location

	memcpy( &copyBuf[flashMemOffset], inBuf, len );

	// reflash entire area

	rc = NVMProgram( (void *)flashMem, copyBuf, FLASH_SIZE, pageBuf );	

	if(rc)
		return(FLASH_NVM_PGM_ERR);

	return(0);
}	

